<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script type="text/javascript" src="CommonUtil/CommonUtil.js"></script>
    <script type="text/javascript" charset="utf-8">
        /**
         * 有一个命令接口
         * 一个执行命令
         * 一个回退命令
         */
        var ReversibleCommmandInterface = new BH.Interface('ReversibleCommmandInterface',
            [
                'execute',
                'undo'
            ]
        )
        var MoveUp = function (cursor) {
            this.cursor = cursor;
        };
        MoveUp.prototype = {
            constructor:MoveUp,
            execute:function () {
                this.cursor.move(0,-10);
            },
            undo:function () {
                this.cursor.move(0,10);
            }
        };
        var MoveDown = function (cursor) {
            this.cursor = cursor;
        };
        MoveDown.prototype = {
            constructor:MoveDown,
            execute:function () {
                this.cursor.move(0,10);
            },
            undo:function () {
                this.cursor.move(0.-10);
            }
        };
        var MoveLeft = function (cursor) {
            this.cursor = cursor;
        };
        MoveLeft.prototype = {
            constructor:MoveLeft,
            execute:function () {
                this.cursor.move(-10,0);
            },
            undo:function () {
                this.cursor.move(10,0);
            }
        };
        var MoveRight = function (cursor) {
            this.cursor = cursor;
        };
        MoveRight.prototype = {
            constructor:MoveRight,
            execute:function () {
                this.cursor.move(10,0);
            },
            undo:function () {
                this.cursor.move(-10,0);
            }
        }
        //模拟当前的接收这
        /**
         *
         * @param width
         * @param height
         * @param parent
         * @constructor
         * width,height:代表外层div
         */
        var Cursor = function (width,height,parent) {
            this.width = width;
            this.height = height;
            //移动的元素的具体位置
            this.position = {
                x:width/2,
                y:height/2
            };
            this.canvas = document.createElement('canvas');
            this.canvas.width = width;
            this.canvas.height = height;
            parent.appendChild(this.canvas);
            //canvas上下文元素(画布的核心元素)
            this.ctx = this.canvas.getContext('2d');
            this.ctx.fillStyle = 'red';
            //初始化位置
            this.move(0,0);
        }
        Cursor.prototype = {
            constructor:Cursor,
            move:function (x,y) {
                this.position.x += x;
                this.position.y += y;
                this.ctx.clearRect(0,0,this.width,this.height);
                //画出方块
                this.ctx.fillRect(this.position.x,this.position.y,20,20);
            }
        }
        /*
         * 应该有一个命令集合【数组】，
         * 目的就是为了当执行每一个一个命令之前，
         * 把该命令放入到集合中。
         * 命令对象在执行真的操作之前，应该把命令放到集合中
         * 也就是在原始命令类上加一些新特性，特别适合（装饰者模式）
         */
        //当前是一个装饰类
        var UndoDecorator  = function (command,undoStack) {
            this.command = command;
            this.undoStack = undoStack;
        };
        UndoDecorator.prototype = {
            constructor:UndoDecorator,
            execute:function () {
                this.undoStack.push(this.command);
                this.command.execute();
            },
            undo:function () {
                this.command.undo();
            }
        };
        /*
         *完善HTML元素即可四个按钮[明令]
         */
        var CommandButton = function (label,command,parent) {
            BH.Interface.ensureImplements(command,ReversibleCommmandInterface);
            this.element = document.createElement('button');
            this.element.innerHTML = label;
            parent.appendChild(this.element);
            BH.EventUtil.addHandler(this.element,'click',function () {
                command.execute();
            })
        };
        var UndoButton = function (label,parent,undoStack) {
            this.element = document.createElement('button');
            this.element.innerHTML = label;
            parent.appendChild(this.element);
            BH.EventUtil.addHandler(this.element,'click',function () {
                if(undoStack.length==0){
                    alert('已经没有命令了，是最后一步回退操作！');
                    return;
                }
                //把最后一次命令拿出来，然后直接执行回退操作
                var lastCommmand = undoStack.pop();
                lastCommmand.undo();
            })
        };
        window.onload = function () {
            var body = document.getElementsByTagName('body')[0];
            var cursor = new Cursor(400,400,body);
            var undoStack = [];
            //客户，创建命令
            var upCommand = new UndoDecorator(new MoveUp(cursor),undoStack);
            var downCommand = new UndoDecorator(new MoveDown(cursor),undoStack);
            var leftCommand = new UndoDecorator(new MoveLeft(cursor),undoStack);
            var rightCommand = new UndoDecorator(new MoveRight(cursor),undoStack);
            var upBtn = new CommandButton('up',upCommand,body);
            var downBtn = new CommandButton('down',downCommand,body);
            var leftBtn = new CommandButton('left',leftCommand,body);
            var rightBtn = new CommandButton('right',rightCommand,body);
            var undoBtn = new UndoButton('undo',body,undoStack);
        }
    </script>
</head>
<body>
</body>
</html>